#include "component/Collider.h"
#include "GameObject.h"
#include "Messenger.h"
#include "event/Event_Physics_Collider.h"


using namespace Boon;



Boon::Collider::Collider( const char* compName, Boon::GameObject* g )
	: GameComponent( compName, g ), m_Flags( 0 ), m_Material( nullptr )
{
	
}

bool Boon::Collider::Register( const ComponentID& id, const IObserverPhysicsStrong& observer )
{
	auto result = m_Observer.find( id );
	if( result == m_Observer.end() )
	{
		m_Observer[id] = observer;
		return true;
	}
	return false;
}

bool Boon::Collider::Remove( const ComponentID& id )
{
	auto result = m_Observer.find( id );
	if( result != m_Observer.end() )
	{
		m_Observer.erase( id );
		return true;
	}
	return false;
}

void Boon::Collider::OnCreate()
{
	Shared_ptr<Event_Physics_Collider>e( new Event_Physics_Collider( Event_Physics_Collider::C_CREATED, *this ) );
	Messenger::GetInstance().Bang( e );
}

void Boon::Collider::OnEnable()
{

}

void Boon::Collider::OnStart()
{

}

void Boon::Collider::Update()
{
	// Collider has been marked as dirty due to changing members
	if( ( m_Flags & CF_DIRTY ) > 0 )
	{
		Shared_ptr<Event_Physics_Collider>e( new Event_Physics_Collider( Event_Physics_Collider::C_UPDATED, *this ) );
		Messenger::GetInstance().Bang( e );
		m_Flags &= ~CF_DIRTY;
	}
}

void Boon::Collider::LateUpdate()
{

}

void Boon::Collider::OnDisable()
{

}

void Boon::Collider::OnDestroy()
{

}

void Boon::Collider::OnTriggerEnter( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnTriggerEnter, collider );
}

void Boon::Collider::OnTriggerExit( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnTriggerExit, collider );
}

void Boon::Collider::OnTriggerStay( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnTriggerStay, collider );
}

void Boon::Collider::OnCollisionEnter( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnCollisionEnter, collider );
}

void Boon::Collider::OnCollisionExit( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnCollisionExit, collider );
}

void Boon::Collider::OnCollisionStay( const Collider& collider )
{
	NotifyObserver( &IObserverPhysics::OnCollisionStay, collider );
}

void Boon::Collider::NotifyObserver( void (IObserverPhysics::*observerCallback)( const Collider& ), const Collider& c  )
{
	auto iter = m_Observer.begin();
	auto end = m_Observer.end();

	while( iter != end )
	{
		// collision - trigger callback functions implemented through IObserverPhysics
		(iter->second.Get()->*observerCallback)( c );
		++iter;
	}
}